package com.ruoyi.system.service.impl;

import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.system.domain.SysDataAsset;
import com.ruoyi.system.domain.SysDataLineage;
import com.ruoyi.system.mapper.SysDataLineageMapper;
import com.ruoyi.system.service.ISysDataAssetService;
import com.ruoyi.system.service.ISysDataLineageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 血缘关系Service业务层处理
 * 
 * @author ruoyi
 */
@Service
public class SysDataLineageServiceImpl implements ISysDataLineageService
{
    @Autowired
    private SysDataLineageMapper sysDataLineageMapper;

    @Autowired
    private ISysDataAssetService sysDataAssetService;

    /**
     * 查询血缘关系
     * 
     * @param lineageId 血缘关系ID
     * @return 血缘关系
     */
    @Override
    public SysDataLineage selectSysDataLineageById(Long lineageId)
    {
        return sysDataLineageMapper.selectSysDataLineageById(lineageId);
    }

    /**
     * 查询资产的血缘图谱数据
     */
    @Override
    public Map<String, Object> getLineageGraph(Long assetId, int depth) {
        Map<String, Object> result = new HashMap<>();
        Set<Long> visited = new HashSet<>();
        List<Map<String, Object>> nodes = new ArrayList<>();
        List<Map<String, Object>> links = new ArrayList<>();

        // 递归查询上下游血缘
        buildLineageGraph(assetId, depth, visited, nodes, links, true);
        buildLineageGraph(assetId, depth, visited, nodes, links, false);

        result.put("nodes", nodes);
        result.put("links", links);
        return result;
    }

    /**
     * 构建血缘图谱
     * @param assetId 资产ID
     * @param depth 剩余查询深度
     * @param visited 已访问节点
     * @param nodes 节点列表
     * @param links 边列表
     * @param isUpstream 是否查询上游
     */
    private void buildLineageGraph(Long assetId, int depth, Set<Long> visited, 
                                  List<Map<String, Object>> nodes, 
                                  List<Map<String, Object>> links, 
                                  boolean isUpstream) {
        if (depth <= 0 || visited.contains(assetId)) {
            return;
        }

        // 添加当前节点
        SysDataAsset asset = sysDataAssetService.selectSysDataAssetById(assetId);
        if (asset != null) {
            visited.add(assetId);
            Map<String, Object> node = new HashMap<>();
            node.put("id", assetId);
            node.put("name", asset.getAssetName());
            node.put("type", asset.getAssetType());
            node.put("desc", asset.getAssetDesc());
            nodes.add(node);

            // 查询上下游
            List<SysDataLineage> lineages = isUpstream 
                ? sysDataLineageMapper.selectUpstreamLineage(assetId)
                : sysDataLineageMapper.selectDownstreamLineage(assetId);

            for (SysDataLineage lineage : lineages) {
                Long relatedAssetId = isUpstream ? lineage.getSourceAssetId() : lineage.getTargetAssetId();
                String sourceId = isUpstream ? relatedAssetId.toString() : assetId.toString();
                String targetId = isUpstream ? assetId.toString() : relatedAssetId.toString();

                // 添加边
                Map<String, Object> link = new HashMap<>();
                link.put("source", sourceId);
                link.put("target", targetId);
                link.put("relation", lineage.getRelationType());
                links.add(link);

                // 递归查询
                buildLineageGraph(relatedAssetId, depth - 1, visited, nodes, links, isUpstream);
            }
        }
    }

    /**
     * 查询上游血缘
     */
    @Override
    public List<SysDataLineage> selectUpstreamLineage(Long targetAssetId) {
        return sysDataLineageMapper.selectUpstreamLineage(targetAssetId);
    }

    /**
     * 查询下游血缘
     */
    @Override
    public List<SysDataLineage> selectDownstreamLineage(Long sourceAssetId) {
        return sysDataLineageMapper.selectDownstreamLineage(sourceAssetId);
    }

    /**
     * 查询血缘关系列表
     * 
     * @param sysDataLineage 血缘关系
     * @return 血缘关系
     */
    @Override
    public List<SysDataLineage> selectSysDataLineageList(SysDataLineage sysDataLineage)
    {
        return sysDataLineageMapper.selectSysDataLineageList(sysDataLineage);
    }

    /**
     * 保存表到表的血缘关系
     */
    @Override
    public void saveTableLineage(String sourceTableName, String targetTableName, 
                                String relationType, Long operationId) {
        // 获取或创建资产
        Long sourceAssetId = sysDataAssetService.getOrCreateAsset(sourceTableName,"table",sourceTableName );
        Long targetAssetId = sysDataAssetService.getOrCreateAsset(targetTableName, "table", targetTableName);

        // 保存血缘关系
        SysDataLineage lineage = new SysDataLineage();
        lineage.setSourceAssetId(sourceAssetId);
        lineage.setTargetAssetId(targetAssetId);
        lineage.setRelationType(relationType);
        lineage.setOperationId(operationId);
        lineage.setCreateTime(DateUtils.getNowDate());
        sysDataLineageMapper.insertSysDataLineage(lineage);
    }

    /**
     * 新增血缘关系
     * 
     * @param sysDataLineage 血缘关系
     * @return 结果
     */
    @Override
    public int insertSysDataLineage(SysDataLineage sysDataLineage)
    {
        sysDataLineage.setCreateTime(DateUtils.getNowDate());
        return sysDataLineageMapper.insertSysDataLineage(sysDataLineage);
    }

    /**
     * 修改血缘关系
     * 
     * @param sysDataLineage 血缘关系
     * @return 结果
     */
    @Override
    public int updateSysDataLineage(SysDataLineage sysDataLineage)
    {
        return sysDataLineageMapper.updateSysDataLineage(sysDataLineage);
    }

    /**
     * 删除血缘关系对象
     * 
     * @param lineageId 血缘关系ID
     * @return 结果
     */
    @Override
    public int deleteSysDataLineageById(Long lineageId)
    {
        return sysDataLineageMapper.deleteSysDataLineageById(lineageId);
    }

    /**
     * 批量删除血缘关系
     * 
     * @param lineageIds 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteSysDataLineageByIds(Long[] lineageIds)
    {
        return sysDataLineageMapper.deleteSysDataLineageByIds(lineageIds);
    }

}
